﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;

namespace Pg.BioMedics.SDR.Web.Controls
{
    /// <summary>
    /// Base class for user views hosted in ViewHost control. This control 
    /// supports view result mapping, views redirection and properties mapping between views
    /// </summary>
    public abstract class BaseHostedView : Spring.Web.UI.UserControl, IHostedView
    {
        #region Fields
        
        private IViewNavigator viewNavigator;
        private HostedViewParameters viewParameters;        

        #endregion

        #region Properties

        /// <summary>
        /// Gets view parameters
        /// </summary>
        protected object[] Parameters
        {
            get
            {
                if (this.viewParameters != null)
                    return this.viewParameters.Parameters;
                else
                    return null;
            }
        }

        /// <summary>
        /// Gets name of the view to which return method woudl navigate
        /// </summary>
        protected string ReturnViewName
        {
            get
            {
                if (this.viewParameters != null)
                    return this.viewParameters.ReturnViewName;
                else
                    return null;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Navigates to given view registered in Viewhost control. This method 
        /// will additionally reassign all properties values defined  
        /// </summary>
        /// <param name="viewName">Target view name</param>
        /// <param name="mappings">Target mappings</param>
        protected void Navigate(string viewName, params PropertyMapping[] mappings)
        {
            // prepare parameter values
            foreach (PropertyMapping mapping in mappings)
                mapping.ExtractValue(this);

            // load view
            this.ViewNavigator.LoadView(viewName, new HostedViewParameters() { Mappings = mappings });
        }

        /// <summary>
        /// Navigates to the given view with given 
        /// parameters.
        /// </summary>
        /// <param name="viewName">View name</param>
        /// <param name="parameters">View parameters</param>
        protected void Navigate(string viewName, params object[] parameters)
        {
            this.viewNavigator.LoadView(viewName, new HostedViewParameters() { Parameters = parameters });
        }

        /// <summary>
        /// Navigates to the given view. Suplies to the navigated view
        /// information about return view and parameters
        /// </summary>
        /// <param name="viewName">View name</param>
        /// <param name="returnViewName">Return view name</param>
        /// <param name="parameters">View parameters</param>
        protected void Navigate(string viewName, string returnViewName, params object[] parameters)
        {
            this.viewNavigator.LoadView(viewName, new HostedViewParameters() { Parameters = parameters, ReturnViewName = returnViewName });
        }

        /// <summary>
        /// Navigate backword to the source view if returnView 
        /// is specified in parameters
        /// </summary>
        protected void Return()
        {
            if (!String.IsNullOrEmpty(ReturnViewName))
                this.viewNavigator.LoadView(ReturnViewName);  
        }

        /// <summary>
        /// Navigates backword with given parameters
        /// </summary>
        /// <param name="parameters">Target view parameters</param>
        protected void Return(params object[] parameters)
        {
            if (!String.IsNullOrEmpty(ReturnViewName))
                this.viewNavigator.LoadView(ReturnViewName, new HostedViewParameters() { Parameters = parameters });  
        }

        /// <summary>
        /// When overriden in derived view loads view parameters supplied 
        /// by Navigate method
        /// </summary>
        /// <param name="parameters">List of view parameters</param>
        protected virtual void LoadParameters(object[] parameters) { }

        /// <summary>
        /// When overriden in derived view loads view model
        /// </summary>
        /// <param name="savedViewModel">Saved view model</param>
        protected virtual void LoadViewModel(object savedViewModel) { }

        /// <summary>
        /// When overriden in derived view saves view model
        /// </summary>
        /// <returns>View model</returns>
        protected virtual object SaveViewModel() { return null; }

        #endregion

        #region Overriden methods

        protected sealed override void LoadModel(object savedModel)
        {
            if (savedModel is object[])
                if ((string)((object[])savedModel)[2] == this.ToString())
                {
                    if (((object[])savedModel)[0] is HostedViewParameters)
                        this.viewParameters = ((object[])savedModel)[0] as HostedViewParameters;

                    LoadViewModel(((object[])savedModel)[1]);
                }

        }

        protected sealed override object SaveModel()
        {
            object viewModel = SaveViewModel();
            return new object[] { this.viewParameters, viewModel, this.ToString() };
        }

        #endregion

        #region IHostedView Members

        /// <summary>
        /// Sets view parameter
        /// </summary>
        public object Parameter
        {
            set 
            { 
                if (value is HostedViewParameters)
                {
                    this.viewParameters = value as HostedViewParameters;
                    if (viewParameters.Mappings != null)
                        foreach (PropertyMapping mapping in viewParameters.Mappings)
                            mapping.ApplyValue(this);

                    if (viewParameters.Parameters != null)
                        LoadParameters(viewParameters.Parameters);
                }
            }
        }

        /// <summary>
        /// Gets / sets view navigator
        /// </summary>
        public IViewNavigator ViewNavigator
        {
            get
            {
                return this.viewNavigator;
            }
            set
            {
                this.viewNavigator = value;
            }
        }

        #endregion 
    }
}
